package indi.zhifa.recipe.bailan.busy.auth.service.impl;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import indi.zhifa.recipe.bailan.framework.auth.impl.dao.service.IAuthNodeRelevantDao;
import indi.zhifa.recipe.bailan.framework.auth.impl.dao.service.IUserDbService;
import indi.zhifa.recipe.bailan.framework.auth.impl.entity.po.AuthNodeEntity;
import indi.zhifa.recipe.bailan.framework.auth.impl.entity.po.DomainEntity;
import indi.zhifa.recipe.bailan.framework.auth.impl.entity.po.UserEntity;
import indi.zhifa.recipe.bailan.framework.auth.impl.util.AppConst;
import indi.zhifa.recipe.bailan.framework.auth.impl.util.ITokenUtil;
import indi.zhifa.recipe.bailan.busy.auth.dao.service.ICompanyDbService;
import indi.zhifa.recipe.bailan.busy.auth.dao.service.IDeviceDbService;
import indi.zhifa.recipe.bailan.framework.auth.impl.entity.dto.TokenObject;
import indi.zhifa.recipe.bailan.busy.auth.entity.dto.device.DeviceCreateDto;
import indi.zhifa.recipe.bailan.busy.auth.entity.dto.device.DeviceEditDto;
import indi.zhifa.recipe.bailan.busy.auth.entity.dto.device.DeviceInitDto;
import indi.zhifa.recipe.bailan.busy.auth.entity.po.*;
import indi.zhifa.recipe.bailan.busy.auth.service.IDeviceService;
import indi.zhifa.recipe.bailan.framework.auth.entity.dto.TokenAuthNodeDto;
import indi.zhifa.recipe.bailan.framework.common.entity.exception.ServiceException;
import indi.zhifa.recipe.bailan.framework.mysql.entity.annotations.ZfFacade;
import indi.zhifa.recipe.bailan.framework.mysql.utils.DbDtoEntityUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.InputStream;
import java.util.*;

@RequiredArgsConstructor
@Slf4j
@ZfFacade(name = "设备")
public class DeviceServiceImpl implements IDeviceService {

    private final IDeviceDbService mDeviceDbService;
    private final IAuthNodeRelevantDao mDepartmentRelevantDao;
    private final ICompanyDbService mCompanyDbService;
    private final IUserDbService mUserDbService;
    private final ITokenUtil mTokenUtil;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void init() {
        ClassPathResource classPathResource = new ClassPathResource("device.json");
        byte[] configData = null;
        try {
            InputStream inputStream = classPathResource.getInputStream();
            configData = inputStream.readAllBytes();
        } catch (Exception ex) {
            log.error("缺失配置文件 " + "device.json "+ex);
            return;
        }
        JSONObject deviceInitConfigData = JSON.parseObject(configData);
        JSONArray deviceInitConfigArray = deviceInitConfigData.getJSONArray("data");
        List<DeviceEntity> savingDeviceList = new ArrayList<>();
        List<DeviceEntity> editingDeviceList = new ArrayList<>();
        DomainEntity domainEntity = mDepartmentRelevantDao.domain_check("zf-mgr");
        List<DeviceInitDto> deviceInitDtoList = new ArrayList<>();
        Set<String> deviceCodeSet = new HashSet<String>();
        for(int i=0;i<deviceInitConfigArray.size();i++){
            DeviceInitDto deviceInitDto = deviceInitConfigArray.getObject(i,DeviceInitDto.class);
            deviceInitDtoList.add(deviceInitDto);
            if(deviceCodeSet.contains(deviceInitDto.getCode())){
                throw new ServiceException("设备码"+deviceInitDto.getCode()+"重复");
            }
            deviceCodeSet.add(deviceInitDto.getCode());
        }

        for(DeviceInitDto deviceInitDto : deviceInitDtoList){
            DeviceEntity orgDeviceEntity = findByCode(deviceInitDto.getCode());
            AuthNodeEntity authNodeEntity = mDepartmentRelevantDao.authNode_check(domainEntity.getId(),deviceInitDto.getDepCode());
            if(null != orgDeviceEntity){
                if(!orgDeviceEntity.getGroupAuthId().equals(authNodeEntity.getId())){
                    orgDeviceEntity.setGroupAuthId(authNodeEntity.getId());;
                    orgDeviceEntity.setGroupAuthCascade(authNodeEntity.getCascade());
                }
                DeviceEntity editingDeviceEntity = DbDtoEntityUtil.editByDto(orgDeviceEntity,deviceInitDto,DeviceEntity.class);
                editingDeviceList.add(editingDeviceEntity);
            }else{
                DeviceEntity newDeviceEntity = DbDtoEntityUtil.createFromDto(deviceInitDto,DeviceEntity.class);
                newDeviceEntity.setGroupAuthId(authNodeEntity.getId());
                newDeviceEntity.setGroupAuthCascade(authNodeEntity.getCascade());
                String companyName = deviceInitDto.getCompanyName();
                CompanyEntity companyEntity = mCompanyDbService.findByName(companyName);
                if(null != companyEntity){
                    newDeviceEntity.setCompanyAuthId(companyEntity.getAuthId());
                    newDeviceEntity.setCompanyName(companyEntity.getName());
                }else{
                    newDeviceEntity.setCompanyAuthId(-1L);
                    newDeviceEntity.setCompanyName("未定义");
                }
                String createUser = deviceInitDto.getCreateUser();
                Long userId = mUserDbService.findByUserName(createUser);
                if(null != userId){
                    UserEntity userEntity = mUserDbService.check(userId);
                    newDeviceEntity.setCreateBy(userEntity.getId());
                }
                savingDeviceList.add(newDeviceEntity);
            }
        }
        mDeviceDbService.saveBatch(savingDeviceList);
        mDeviceDbService.updateBatchById(editingDeviceList);
    }

    @Override
    public List<DeviceEntity> list() {
        return mDeviceDbService.list();
    }

    @Override
    public DeviceEntity info(Long pId) {
        return mDeviceDbService.check(pId);
    }

    @Override
    public DeviceEntity create(DeviceCreateDto pDeviceCreateDto) {
        DeviceEntity deviceEntity = DbDtoEntityUtil.createFromDto(pDeviceCreateDto,DeviceEntity.class);
        TokenObject tokenObject = mTokenUtil.getTokenObject();
        Map<String, TokenAuthNodeDto> authNodeDtoMap = tokenObject.getAuthNodeInfo();
        TokenAuthNodeDto tokenAuthNodeDto = authNodeDtoMap.get(AppConst.DOMAIN_ZF_MERCHANT);
        Long authId = tokenAuthNodeDto.getAuthId();
        deviceEntity.setCompanyAuthId(authId);
        CompanyEntity companyEntity = mCompanyDbService.findByAuthId(authId);
        if(null == companyEntity){
            throw new ServiceException("用户鉴权数据错误，没有找到authId为"+authId+"的公司");
        }
        deviceEntity.setCompanyName(companyEntity.getName());
        deviceEntity.setGroupAuthId(-1L);
        deviceEntity.setGroupAuthCascade("null");
        mDeviceDbService.save(deviceEntity);
        return deviceEntity;
    }

    @Override
    public DeviceEntity edit(Long pId, DeviceEditDto pDeviceEditDto) {
        DeviceEntity orgEntity = mDeviceDbService.check(pId);
        DeviceEntity newEntity = DbDtoEntityUtil.editByDto(orgEntity,pDeviceEditDto,DeviceEntity.class);
        mDeviceDbService.updatePull(pId,newEntity);
        return newEntity;
    }

    @Override
    public Page<DeviceEntity> page(int pCurrent, int pSize, String pCode, String pName,Long pCreateUserId, Long pCompanyAuthId) {
        Page<DeviceEntity> pageCfg = new Page<DeviceEntity>(pCurrent,pSize);
        LambdaQueryWrapper<DeviceEntity> queryWrapper = Wrappers.<DeviceEntity>lambdaQuery()
                .eq(StringUtils.hasText(pCode),DeviceEntity::getCode,pCode)
                .eq(null!=pCreateUserId,DeviceEntity::getCreateBy,pCreateUserId)
                .eq(null!=pCompanyAuthId,DeviceEntity::getCompanyName,pCompanyAuthId)
                .like(StringUtils.hasText(pName),DeviceEntity::getName,pName);
        return mDeviceDbService.page(pageCfg,queryWrapper);
    }


    DeviceEntity findByCode(String pCode){
        Long id = mDeviceDbService.findByCode(pCode);
        if(null != id){
            return mDeviceDbService.check(id);
        }
        return null;
    }

}
